package experiment5;

import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

public class RandomNumber extends Random {
    long seed;
    long multiplier = 0x5DEECE66DL;
    long addend = 0xBL;
    private static final AtomicLong seedUniquifier
            = new AtomicLong(8682522807148012L);

    private static long seedUniquifier() {
        for (;;) {
            long current = seedUniquifier.get();
            long next = current * 1181783497276652981L;
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }

    RandomNumber(){
        this.seed = seedUniquifier() ^ System.nanoTime();
    }

    public int nextInt(){
        return (int)(next() >> 32);
    }
    public int nextInt(int bound){
        return (int)(next() >>> 33) % bound;
    }

    public long nextLong(){
        return next()>>>1;
    }

    public boolean nextBoolean(){
        return (next() >> 63 ) == 0;
    }

    public float nextFloat(){
        return nextInt(Integer.MAX_VALUE) / (float)Integer.MAX_VALUE;
    }

    public double nextDouble(){
        return nextInt(Integer.MAX_VALUE) / (double)Integer.MAX_VALUE;
    }
    public long next(){
        return this.seed = seed * multiplier + addend;
    }

    public static void main(String[] args) {
        RandomNumber randomNumber = new RandomNumber();
        Random random = new Random();
        int i = 10000;
        while (i-- != 0) {
//            System.out.println( randomNumber.nextFloat() + "," + random.nextFloat() +","+ randomNumber.seed);
//            System.out.println( randomNumber.nextInt() + "," + random.nextInt() +","+ randomNumber.seed);
//            System.out.println( randomNumber.nextInt(1000) + "," + random.nextInt(1000) +","+ randomNumber.seed);
//            System.out.println( randomNumber.nextDouble() + "," + random.nextDouble() +","+ randomNumber.seed);
//            System.out.println( randomNumber.nextBoolean() + "," + random.nextBoolean() +","+ randomNumber.seed);
            System.out.println(randomNumber.nextLong());
        }
    }

}
